package com.winit.schedule.task.tracker.schema;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.Assert;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.winit.schedule.core.task.ScheduleTaskDefine;
import com.winit.schedule.core.utils.StringUtils;

public class UScheduleBeanDefinitionParser implements BeanDefinitionParser {

    private static final Logger logger = LoggerFactory.getLogger(UScheduleBeanDefinitionParser.class);

    public UScheduleBeanDefinitionParser(){
    }

    public BeanDefinition parse(Element element, ParserContext parserContext) {
        String taskName = element.getAttribute("taskName");
        String className = element.getAttribute("class");

        Assert.hasLength(taskName, "The taskName property of uschedule:task cannot be empty");
        Assert.hasLength(className, "The class property of uschedule:task cannot be empty");

        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        try {
            beanDefinition.setBeanClass(Class.forName(className));
        } catch (ClassNotFoundException e) {
            if (logger.isDebugEnabled()) {
                logger.debug("uschedule bean parser failure, taskName:" + taskName + ", class:" + className);
            }
            throw new BeanCreationException("uschedule bean parser failure.", e);
        }
        beanDefinition.setLazyInit(false);

        String _beanName = taskName;

        if (StringUtils.isBlank(_beanName)) {
            _beanName = className;
        }
        
        _beanName = ScheduleTaskDefine.BEAN_PREFIX + _beanName;

        parserContext.getRegistry().registerBeanDefinition(_beanName, beanDefinition);

        parseProperties(element.getChildNodes(), beanDefinition);

        return beanDefinition;
    }

    private static void parseProperties(NodeList nodeList, RootBeanDefinition beanDefinition) {
        if (nodeList != null && nodeList.getLength() > 0) {
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (node instanceof Element) {
                    if ("property".equals(node.getNodeName()) || "property".equals(node.getLocalName())) {
                        String name = ((Element) node).getAttribute("name");
                        if (name != null && name.length() > 0) {
                            String value = ((Element) node).getAttribute("value");
                            String ref = ((Element) node).getAttribute("ref");
                            if (value != null && value.length() > 0) {
                                beanDefinition.getPropertyValues().addPropertyValue(name, value);
                            } else if (ref != null && ref.length() > 0) {
                                beanDefinition.getPropertyValues()
                                    .addPropertyValue(name, new RuntimeBeanReference(ref));
                            } else {
                                throw new UnsupportedOperationException("Unsupported <property name=\""
                                                                        + name
                                                                        + "\"> sub tag, Only supported <property name=\""
                                                                        + name
                                                                        + "\" ref=\"...\" /> or <property name=\""
                                                                        + name + "\" value=\"...\" />");
                            }
                        }
                    }
                }
            }
        }
    }

}
